home *** CD-ROM | disk | FTP | other *** search
- Path: keats.ugrad.cs.ubc.ca!not-for-mail
- From: c2a192@ugrad.cs.ubc.ca (Kazimir Kylheku)
- Newsgroups: comp.lang.c,comp.unix.programmer
- Subject: Re: Q: '\n' character
- Date: 16 Apr 1996 16:33:56 -0700
- Organization: Computer Science, University of B.C., Vancouver, B.C., Canada
- Message-ID: <4l1ap4INNhsc@keats.ugrad.cs.ubc.ca>
- References: <4kj66f$k0o@ren.cei.net> <4ku8f9$d3o@mark.ucdavis.edu> <4kumbqINNgcr@mayne.ugrad.cs.ubc.ca> <4l13uu$mva@mark.ucdavis.edu>
- NNTP-Posting-Host: keats.ugrad.cs.ubc.ca
-
- In article <4l13uu$mva@mark.ucdavis.edu>,
- James Knight <knight@quad.cs.ucdavis.edu> wrote:
- >Yes, but which one is faster. I did this experiment for a class I was teaching,
- >where I compared all combinations of fgetc, fgets, fputc and fputs for a cat
- >program that does line by line reading. The fgetc/fputc combination ran in
- >about 10 seconds (I think I was reading 1MB of text), the fgets/fputc and
- >fgetc/fputs combinations ran in about 6.5-7 seconds and the fgets/fputs
- >combination ran in 3.5 seconds. I can post more details about this, if you
- >like.
-
- Please do! Mind you, a cat program is somewhat trivial. In implementing cat with
- fgets()/fputs(), you don't have to care whether there is a newline at the end!
- fgets()/fputs() seem almost ideally matched to a cat-like program, though
- fread() and fwrite() are likely to do even better since they don't have to look
- for a newline at all.
-
- But once you start having to scan the buffer with strlen(), strchr() and
- friends, the advantage of using fgets() may diminish.
-
- Also, you used fputc() and fgetc(). These are not likely to be as fast as the
- getc() and putc() macro equivalents which access the FILE structure's buffer
- directly. (Do you know the implementation details of these functions/macros on
- the system that served as your testbench?)
-
- On this system, when I write
-
- while((c = getc(in)) != EOF) putc(out,c);
-
- I get something like this, after the pre-processing stage and a little cosmetic
- cleanup
-
-
- while ((c = ((in)->_IO_read_ptr >= (in)->_IO_read_end
- ? __uflow(in)
- : *(unsigned char *) (in)->_IO_read_ptr++)) != (-1))
-
- (((c)->_IO_write_ptr >= (c)->_IO_write_end)
- ? __overflow(c, (unsigned char) (out))
- : (unsigned char) (*(c)->_IO_write_ptr++ = (out)));
-
- It looks a little messy, but it's the whole logic for copying from one buffered
- IO stream to another, minus the definitions for the __uflow and __overflow glue
- functions. Let's see what optimized x86 code looks like for the construct:
-
-
- .file "test2.c"
- gcc2_compiled.:
- ___gnu_compiled_c:
- .text
- .align 4
- .globl _foo
- _foo:
- pushl %esi
- pushl %ebx
- movl 12(%esp),%esi
- movl 16(%esp),%ebx
- .align 2,0x90
- L10:
- movl 4(%esi),%eax
- cmpl %eax,8(%esi)
- ja L13
- pushl %esi
- call ___uflow
- addl $4,%esp
- jmp L14
- .align 4,0x90
- L13:
- movzbl (%eax),%eax
- incl 4(%esi)
- L14:
- cmpl $-1,%eax
- je L11
- movl 20(%ebx),%edx
- cmpl %edx,24(%ebx)
- ja L15
- andl $255,%eax
- pushl %eax
- pushl %ebx
- call ___overflow
- addl $8,%esp
- jmp L10
- .align 4,0x90
- L15:
- movb %al,(%edx)
- incl 20(%ebx)
- jmp L10
- .align 4,0x90
- L11:
- popl %ebx
- popl %esi
- ret
-
- That's not bad for what it does. (I put a simple function wrapper around the
- loop, declared the in, out and c variables, and compiled with -O6
- -fomit-frame-pointer).
-
- I suspect that if your cat program had been rewritten to do a dumb getc()
- putc() loop until EOF, it would have beat the fgets(), just by virtue of not
- having to 1) make a function call, 2) look for newlines and 3) copy the data
- into a redundant bounce buffer that acts as a middleman between two FILE stream
- buffers.
- --
- I'm not really a jerk, but I play one on Usenet.
-